package com.slofzx.nuoda.evaluation.project.util;

import com.alibaba.fastjson.JSON;
import com.slofzx.nuoda.common.config.Type;
import com.slofzx.nuoda.common.enums.CommonResultEnum;
import com.slofzx.nuoda.common.enums.SysPermission;
import com.slofzx.nuoda.common.exception.ServiceException;
import com.slofzx.nuoda.common.util.DataConvertUtil;
import com.slofzx.nuoda.common.vo.PermissionVO;
import com.slofzx.nuoda.common.vo.SysUserVO;
import com.slofzx.nuoda.evaluation.project.enums.DateFormatType;
import com.slofzx.nuoda.evaluation.steretype.ExcelExportConfig;
import com.slofzx.nuoda.evaluation.steretype.ExcelExportItem;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

public class BusiUtil {

    private static final Logger logger = LoggerFactory.getLogger(BusiUtil.class);

    public static final String DELIMITER = "_";
    public static final String USER_HEADER = "user";

    /**
     * 生成 redis key
     *
     * @param keys
     * @return
     */
//    public static String generateRedisKey(String... keys) {
//        return generateBusiKey(keys, RedisConstant.DELIMITER);
//    }
//
//    private static String[] splitRedisKey(String key) {
//        return StringUtils.split(key, RedisConstant.DELIMITER);
//    }

    /**
     * 将数据转换为map
     *
     * @param data
     * @return
     */
    public static Map<String, Object> parseObject2Map(Object data, Map<String, List<ExcelExportItem>> excelExportItemGroupMap) {
        if (data == null) {
            return null;
        }
        ExcelExportConfig excelExportConfig = data.getClass().getAnnotation(ExcelExportConfig.class);
        if (excelExportConfig == null) {
            return null;
        }
        Map<String, Object> result = new HashMap<>();
        List<ExcelExportItem> subList = excelExportItemGroupMap.get(excelExportConfig.name());
        if (subList == null) {
            return result;
        }
        for (ExcelExportItem item : subList) {
            if (item.getGroup().equals(excelExportConfig.name())) {
                result.put(item.getId(), item.getValue(data));
            }
        }
        return result;
    }

    /**
     * 将年份列表数据转换为map
     *
     * @param dataList
     * @return
     */
    public static Map<String, Object> parseYearDataList2Map(List dataList, Map<String, List<ExcelExportItem>> excelExportItemGroupMap, Class clz) {
        if (dataList == null || clz == null) {
            return null;
        }
        ExcelExportConfig excelExportConfig = (ExcelExportConfig) clz.getAnnotation(ExcelExportConfig.class);
        if (excelExportConfig == null) {
            return null;
        }
        Map<String, Object> result = new HashMap<>();
        if (dataList.isEmpty()) {
            return result;
        }
        excelExportConfig = dataList.get(0).getClass().getAnnotation(ExcelExportConfig.class);
        if (excelExportConfig == null) {
            return result;
        }
        List<ExcelExportItem> subList = excelExportItemGroupMap.get(excelExportConfig.name());
        if (subList == null) {
            return result;
        }

        for (ExcelExportItem field : subList) {
            Map<Integer,Object> yearDataMap = new HashMap<>();
            Double sumValue = null,avgValue=null,maxValue=null,minValue=null;
            int index = 1;
            for (Object dataItem : dataList) {
                if(dataItem == null) {
                    continue;
                }
                if (field.getGroup().equals(excelExportConfig.name())) {
                    Object value = field.getValue(dataItem);
                    yearDataMap.put(index,value);
                    result.put(field.getId() + ":" + index++, value);
                    Double doubleValue = DataConvertUtil.parse2Double(value, null);
                    if (doubleValue != null) {
                        if (sumValue == null) {
                            sumValue = doubleValue;
                        } else {
                            sumValue += doubleValue;
                        }
                        if (maxValue == null) {
                            maxValue = doubleValue;
                        } else if(doubleValue>maxValue){
                            maxValue = doubleValue;
                        }
                        if (minValue == null) {
                            minValue = doubleValue;
                        } else if(doubleValue<minValue){
                            minValue = doubleValue;
                        }
                    }
                }
            }
            result.put(field.getId() + ":sum", sumValue);
            result.put(field.getId() + ":max", maxValue);
            result.put(field.getId() + ":min", minValue);
            result.put(field.getId() + ":avg", sumValue==null||dataList.isEmpty()?null:sumValue/dataList.size());
            result.put(field.getId() + "#map", yearDataMap);
        }
        return result;
    }


    /**
     * 生成key
     *
     * @param keys
     * @return
     */
    public static String generateBusiKey(String... keys) {
        return generateBusiKey(keys,DELIMITER);
    }

    /**
     * 切分redis key
     *
     * @param key
     * @return
     */
    public static String[] splitBusiKey(String key) {
        return StringUtils.split(key,DELIMITER);
    }

    /**
     * 生成key
     *
     * @param keys
     * @return
     */
    public static String generateBusiKey(String[] keys, String delimiter) {
        if (keys == null || keys.length == 0) {
            throw new RuntimeException("生成key参数不允许为空");
        }
        StringJoiner stringJoiner = new StringJoiner(delimiter);
        for (int i = 0; i < keys.length; i++) {
            if (StringUtils.isEmpty(keys[i])) {
                continue;
            }
            stringJoiner.add(keys[i]);
        }
        return stringJoiner.toString();
    }

    /**
     * 校验是否有对应的权限
     * @param userVO
     * @param sysPermission
     */
    public static boolean checkPermission(SysUserVO userVO, SysPermission sysPermission) {
        if (userVO.isAdmin()) {
            return true;
        }
        final List<PermissionVO> permissionList = userVO.getPermissionList();
        if (CollectionUtils.isEmpty(permissionList)) {
            return false;
        }
        final List<String> permissionIdList = permissionList.stream().map(PermissionVO::getId).collect(Collectors.toList());
        if (!permissionIdList.contains(sysPermission.getId())) {
            return false;
        }
        return true;
    }

    /**
     * 根据枚举名称获取获取枚举
     *
     * @param name
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getEnumByName(String name, Class<?> clazz) {
        if (StringUtils.isEmpty(name)) {
            return null;
        }
        final Type[] values = (Type[]) clazz.getEnumConstants();
        Type[] var3 = values;
        int var4 = values.length;

        for (int var5 = 0; var5 < var4; ++var5) {
            Type constant = var3[var5];
            if (constant.getName().equalsIgnoreCase(name)) {
                return (T) constant;
            }
        }
        return null;
    }

    /**
     * 根据枚举Id获取获取枚举
     *
     * @param id
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getEnumById(String id, Class<?> clazz) {
        if (StringUtils.isEmpty(id)) {
            return null;
        }
        final Type[] values = (Type[]) clazz.getEnumConstants();
        Type[] var3 = values;
        int var4 = values.length;

        for (int var5 = 0; var5 < var4; ++var5) {
            Type constant = var3[var5];
            if (constant.getId().equalsIgnoreCase(id)) {
                return (T) constant;
            }
        }
        return null;
    }


    /**
     * 对象深拷贝
     *
     * @param object
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T deepCopy(T object, Class<T> clazz) {
        return JSON.parseObject(JSON.toJSONString(object), clazz);
    }

    /**
     * 时间转为字符传
     * @param date
     * @param formatType
     * @return
     */
    public static String dateToString(Date date, DateFormatType formatType) {
        if (Objects.isNull(date)) {
            return null;
        }
        return new DateTime(date).toString(formatType.getId());
    }

    /**
     * 转换为时间
     * @param dateStr
     * @param formatType
     * @return
     */
    public static Date parseDate(String dateStr, DateFormatType formatType) {
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        return DateTime.parse(dateStr, formatType.getId()).toDate();
    }

    public static Date getMonthEndDayByDate(Date date) {
        final DateTime dateTime = new DateTime(date);
        final int maximumValue = dateTime.dayOfMonth().getMaximumValue();
        final DateTime plusDays = dateTime.plusDays(maximumValue);
        return plusDays.plusHours(23).plusSeconds(59).toDate();

       // return new Date();
    }


    public static Date getDate(Integer year, Integer month, Integer day) {
        return new DateTime(year, month, day, 0, 0, 0).toDate();
    }

    public static Date getDate(Integer year, Integer month, Integer day, Integer hour, Integer minute, Integer second) {
        return new DateTime(year, month, day, hour, minute, second).toDate();
    }

    /**
     * 获取两个时间差额 返回 秒数
     * @param startTime
     * @param endTime
     * @return
     */
    public static Long getDiffSeconds(Date startTime, Date endTime) {
        final Interval interval = new Interval(new DateTime(startTime), new DateTime(endTime));
        return interval.toDuration().getStandardSeconds();

    }

    /**
     * 获取某时间与当前时间差额 返回 秒数
     * @param isStart 当前时间是否是开始时间
     * @return
     */
    public static Long getNowDiffSeconds(Date date, boolean isStart) {
        if (isStart) {
            return getDiffSeconds(date, new Date());
        }
        return getDiffSeconds(new Date(), date);

    }

    /**
     * 秒数 转为 xx时：xx分：xx秒
     * @param seconds
     * @return
     */
    public static String formatDuration(long seconds) {
        long hours = seconds / 3600;
        long minutes = (seconds % 3600) / 60;
        long remainingSeconds = seconds % 60;

        return String.format("%d:%02d:%02d", hours, minutes, remainingSeconds);
    }

    public static void main(String[] args) {
        final DateTime dateTime = new DateTime();
        System.out.println(dateTime);
    }

    /**
     * 执行java script返回校验结果
     *
     * @param
     * @return
     */
//    public static <T> T evaJavaScript(String script) {
//        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
//        try {
//            final Object eval = engine.eval(script);
//            return eval == null ? null : (T) eval;
//        } catch (ScriptException e) {
//            logger.error("脚本执行错误",e);
//            throw new FlowServiceException(FlowResultEnum.SCRIPT_ERROR,e);
//        }
//    }

    public static String getRequestHeader(String header) {
        final RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        return ((ServletRequestAttributes) requestAttributes).getRequest().getHeader(header);
    }

    /**
     * 从请求上下文获取userID,使用前是否调用setAttributes
     *
     * @return
     */
    public static String getUserId() {
        final RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        return (String) requestAttributes.getAttribute(USER_HEADER, 0);
    }

    @SuppressWarnings("uncheck")
    public static String formatTpl(String tpl, String... params) {
        return MessageFormat.format(tpl, params);
    }

    /**
     * 校验空值
     * @param value
     * @param errMsg
     */
    public static void checkNotNull(String value, String errMsg) {
        if (StringUtils.isNotEmpty(value)) {
            return;
        }
        throw new ServiceException(errMsg, errMsg, null);
    }
}
